﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace Catalyst.ServiceModel
{
	public static class ServiceHostList
	{
		static readonly object _lock = new object();
		const string codeBlu = "code.blu@frisb.com";
		const string ab = "ashley@starlogik.com";

		static SmtpClient _client = _client = new SmtpClient("smtp.gmail.com", 587)
		{
			EnableSsl = true,
			Credentials = new NetworkCredential(codeBlu, "**logik**", "")
		};

		public static void Open(this List<ServiceHost> source)
		{
			string subject = "starting services on " + Environment.MachineName;
			string body = "";

			Trace.WriteLine(subject);

			_client.Send(codeBlu, ab, subject, body);

			source.ToList().ForEach(s => 
				{
					if (s.Description.Endpoints.Count(e => e.Contract.ContractType != typeof(IMetadataExchange)) > 0)
					{
						s.Faulted += new EventHandler(s_Faulted);

						s.Open();
					}
					else
					{
						Trace.WriteLine(String.Format("Could not open ServiceHost for Service {0} because it has no endpoints.", s.Description.Name));
					}
				});
		}

		public static void Close(this List<ServiceHost> source)
		{
			source.ToList().ForEach(s => 
				{
					if (s.State == CommunicationState.Opened)
					{
						s.Close();
					}
				});
		}

		static void s_Faulted(object sender, EventArgs e)
		{
			ServiceHost host = sender as ServiceHost;

			string subject = String.Format("service {0} faulted on {1}", host.Description.Name, Environment.MachineName);
			string body = "";

			Trace.WriteLine(subject);

			_client.Send(codeBlu, ab, subject, body);

			lock (_lock)
			{
				bool isClosed = false;

				if (host != null)
				{
					try
					{
						host.Close();

						isClosed = true;

						subject = String.Format("service {0} closed on {1}", host.Description.Name, Environment.MachineName);
						body = "";

						Trace.WriteLine(subject);

						_client.Send(codeBlu, ab, subject, body);
					}
					catch (Exception ex)
					{
						try
						{
							host.Abort();

							isClosed = true;

							subject = String.Format("service {0} aborted on {1}", host.Description.Name, Environment.MachineName);
							body = "";

							Trace.WriteLine(subject);

							_client.Send(codeBlu, ab, subject, body);
						}
						catch (Exception ex2)
						{
							subject = String.Format("service {0} could not abort on {1}", host.Description.Name, Environment.MachineName);
							body = String.Format("{0}\r\n\r\n{1}", ex2.Message, ex2.StackTrace);

							Trace.WriteLine(subject + "\r\n" + body);

							_client.Send(codeBlu, ab, subject, body);
						}
					}

					if (isClosed)
					{
						host.Open();

						subject = String.Format("service {0} restarted on {1}", host.Description.Name, Environment.MachineName);
						body = "";

						Trace.WriteLine(subject);

						_client.Send(codeBlu, ab, subject, body);
					}
				}
			}
		}
	}
}
